/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tabla_de_simbolos;

import analizadorlexico.Token;
import arbol_sintactico_abstracto.AST;
import generador_de_codigo.GeneradorDeCodigo;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 *
 * @author Javi
 */
public class Constructor {
    private Token nombre;
    private List<Atributo> parametros, variables;
    private AST ast;
    private int offsetParam,offsetVar;
    private Clase definido;

    public Constructor(Token nombre, Clase definido) {
        this.nombre = nombre;
        parametros = new ArrayList();
        variables = new ArrayList();
        offsetParam = 0;
        offsetVar = 0;
        this.definido = definido;
    }
    
    public void insertarParametro(Token nombre , Tipo tipo) throws ErrorSemantico {
        for(Atributo atributo : parametros){
            if(atributo.getNombre().equals(nombre.getNombre()))
                throw new ErrorSemantico("Ya existe un parametro con el mismo nombre" + nombre.getLinea());
        }
        for(Atributo atributo : variables){
            if(atributo.getNombre().equals(nombre.getNombre()))
                throw new ErrorSemantico("Ya existe una variable de instancia con el mismo nombre. Linea: " + nombre.getLinea());
        }
        parametros.add(new Atributo(nombre,tipo,offsetParam));
        offsetParam++;
    }

    public void insertarVariable(Token nombre, Tipo tipo) throws ErrorSemantico {
        for(Atributo atributo : parametros){
            if(atributo.getNombre().equals(nombre.getLexema()))
                throw new ErrorSemantico("Ya existe un parametro con el mismo nombre. Linea: " + nombre.getLinea());
        }
        for(Atributo atributo : variables){
            if(atributo.getNombre().equals(nombre.getLexema()))
                throw new ErrorSemantico("Ya existe una variable de instancia con el mismo nombre. Linea: " + nombre.getLinea());
        }
        variables.add(new Atributo(nombre,tipo,offsetVar));
        offsetVar--;
    }

    public String getNombre() {
        return nombre.getLexema();
    }

    public int getLinea(){
        return nombre.getLinea();
    }

    public List<Atributo> getParametros() {
        return parametros;
    }

    public List<Atributo> getVariables() {
        return variables;
    }    

    public AST getAst() {
        return ast;
    }

    public void setAst(AST ast) {
        this.ast = ast;
    }

    public int getOffsetParam() {
        return offsetParam;
    }
    
    public int getOffsetParamCod(){
        return offsetParam + 3 ;
    }

    public void setOffsetParam(int offsetParam) {
        this.offsetParam = offsetParam;
    }

    public int getOffsetVar() {
        return offsetVar;
    }

    public void setOffsetVar(int offsetVar) {
        this.offsetVar = offsetVar;
    }

    void chequeoSentencias(Clase clase) throws ErrorSemantico, IOException{
        //Generamos el registro de activacion
        if(this.esConstructor())
            GeneradorDeCodigo.generar(clase.getNombre() + "_Ctor: LOADFP \n");
        else
            if(this.getNombre().equals("main") && !GeneradorDeCodigo.has_main){
                    GeneradorDeCodigo.generar("metodo_" + nombre.getLexema() + ": LOADFP \n");
                    GeneradorDeCodigo.has_main = true;
            }
            else
                GeneradorDeCodigo.generar(clase.getNombre() + "_" + nombre.getLexema() + ": LOADFP \n");
        
        GeneradorDeCodigo.generar("LOADSP \n");
        GeneradorDeCodigo.generar("STOREFP \n");
       /* 
        if(!this.esConstructor() && !((Metodo)this).getTipoRetorno().getNombre().equals("void")){
            GeneradorDeCodigo.generar("RMEM 1 \n");
        }*/
       
        if(!variables.isEmpty())
            GeneradorDeCodigo.generar("RMEM " + variables.size() + "\n");
        
        ast.chequeoSentencias(clase,this);
         //retorno de la unidad
        if(!variables.isEmpty())
            GeneradorDeCodigo.generar("FMEM " + variables.size() + "\n");
        
        GeneradorDeCodigo.generar("STOREFP \n");
        
        //ver RET cuanto
        if(getModMetodo().getModificador().equals("static"))
            GeneradorDeCodigo.generar("RET " + parametros.size() + "\n");
        else
            GeneradorDeCodigo.generar("RET " + (parametros.size() + 1) + "\n");
    }
    
    public boolean contieneVariable(String nombre){
        for(Atributo a : variables){
            if(a.getNombre().equals(nombre))
                return true;
        }
        return false;
    }
    
    public boolean contieneParametro(String nombre){
        for(Atributo a : parametros){
            if(a.getNombre().equals(nombre))
                return true;
        }
        return false;
    }
    
    public boolean esConstructor(){
        return true;
    }
    
    public Clase definido(){
        return definido;
    }
    
    public ModificadorMetodo getModMetodo() {
        return new ModificadorMetodo(new Token("dynamic","dynamic", nombre.getLinea()));
    }
}
